import { Component, OnInit, Output, EventEmitter, Input, ViewChild, TemplateRef, NgZone, HostBinding } from '@angular/core';
import { TreeTableComponent } from '@farris/ui-treetable';
import { NotifyService } from '@farris/ui-notify';
import { FormBindingType, FormExpressionConfig, DomService, DesignViewModelService, FormVariableCategory } from '@farris/designer-services';
// import { ExpressionEditorComponent } from '../expression-editor/expression-editor.component';

// 绑定自定义的字符串
const BINDING_TYPE_CUSTOM = 'Custom';
const BINDING_TYPE_FORM = FormBindingType.Form;
const BINDING_TYPE_LOCAL_VAR = 'LocaleVariable';
const BINDING_TYPE_REMOTE_VAR = 'RemoteVariable';
const BINDING_TYPE_EXPRESSION = 'Expression';



/**
 * 用于属性填写自定义的字符串或绑定变量、字段，选择后的字段和变量不会添加到viewModel.fields节点下。待删，用多值属性编辑器替换。
 */

@Component({
  selector: 'app-binding-custom-editor',
  templateUrl: './binding-custom-editor.component.html',
})
export class BindingCustomEditorComponent implements OnInit {
  @Output() closeModal = new EventEmitter<any>();
  @Output() submitModal = new EventEmitter<any>();
  @Input() value;
  @Input() editorParams: BindingCustomEditorParams;
  @ViewChild('bindingFooter') modalFooter: TemplateRef<any>;
  get modalConfig() {
    return {
      title: this.editorParams.modalTitle || '绑定编辑器',
      width: 1060,
      height: 700,
      showButtons: true
    };
  }
  /** 当前绑定方式 */
  bindingType = BINDING_TYPE_CUSTOM;

  /**
   * 支持的绑定方式数组
   */
  bindingTypeEnumData = [];

  /** 是否支持绑定字段---默认不支持 */
  canBindForm = false;

  /** 是否支持绑定组件变量 */
  canBindLocaleVar = true;

  /** 是否支持绑定表单变量 */
  canBindRemoteVar = true;

  /** 是否支持自定义配置项 */
  canBindCustom = true;


  /** 自定义绑定数据 */
  customBinding: any;

  /** 自定义下拉列表配置项 */
  selectConfig;

  customBoolAndStringRadioValue: any = true;
  customStringValue = '';

  /** 树表数据 */
  treeData = [];

  /** 树表列配置 */
  treeCols = [];

  /** 树表实例 */
  @ViewChild('treeTable') treeTable: TreeTableComponent;

  // 绑定字段树表信息
  fieldsTreeData = [];
  fieldsTreeCols = [{ field: 'name', title: '名称' }, { field: 'bindingField', title: '绑定字段' }];


  // 变量树表信息
  localVarTreeData = [];
  remoteVarTreeData = [];
  variableTreeCols = [{ field: 'name', title: '名称' }, { field: 'code', title: '编号' }];

  /** 当前配置的表达式 */
  originalExpConfig: FormExpressionConfig;

  /** 表达式编辑器参数配置 */
  expressionParams: any = {};

  /** 表达式值 */
  expressionValue = '';

  /** 表达式编辑器实例 */
  // @ViewChild(ExpressionEditorComponent) expressionEditorComponent: ExpressionEditorComponent;

  @HostBinding('class')
  class = 'd-flex f-utils-fill-flex-column h-100';

  /** 日期类控件的展示格式 */
  dateFormat = 'yyyy-MM-dd';
  showDateTime = false;

  constructor(
    private domService: DomService,
    private dgVMService: DesignViewModelService,
    private notifyService: NotifyService,
    private ngZone: NgZone) { }

  ngOnInit() {
    const viewModelId = this.editorParams.viewModelId;
    const viewModel = this.domService.getViewModelById(viewModelId);
    // 字段
    this.fieldsTreeData = this.dgVMService.getAllFields2TreeByVMId(viewModelId);

    // 根组件的组件变量
    if (viewModel.parent) {
      const rootLocalVars = this.domService.getLocaleVariablesByViewModelId(viewModel.parent);
      if (rootLocalVars && rootLocalVars.length) {
        rootLocalVars[0].data.name = '根组件';
        this.localVarTreeData = this.localVarTreeData.concat(rootLocalVars);
      }
    }
    // 当前组件的组件变量
    const localVars = this.domService.getLocaleVariablesByViewModelId(viewModelId);
    this.localVarTreeData = this.localVarTreeData.concat(localVars);

    // 后端变量
    this.remoteVarTreeData = this.domService.getRemoteVariables();

    this.init();
    this.assembleTreeData();
    this.initExpression();
    this.initCustomBoolOrString();
    this.initCustomSelectOrString();

    this.assembleBindingTypeEnumData();
  }


  init() {
    // 初始自定义绑定中的下拉枚举配置
    switch (this.editorParams.customType) {
      case BindingCustomType.boolean: {
        this.selectConfig = this.editorParams.selectConfig || {
          idField: 'value',
          textField: 'text',
          options: [{ value: true, text: 'true' }, { value: false, text: 'false' }]
        };
        break;
      }
      case BindingCustomType.select: {
        this.selectConfig = Object.assign({
          idField: 'value',
          textField: 'text',
          options: []
        }, this.editorParams.selectConfig);
        break;
      }
      case BindingCustomType.booleanOrString: {
        this.selectConfig = this.editorParams.selectConfig || {
          idField: 'value',
          textField: 'text',
          options: [{ value: true, text: 'true' }, { value: false, text: 'false' }, { value: 'string', text: '自定义' }]
        };
        break;
      }
      case BindingCustomType.selectOrString: {
        const idField = this.editorParams.selectConfig.idField;
        const textField = this.editorParams.selectConfig.textField;
        const options = this.editorParams.selectConfig.options.concat({
          [idField]: 'string',
          [textField]: '自定义'
        });
        this.selectConfig = {
          idField,
          textField,
          options
        };
        break;
      }
      case BindingCustomType.datetime: {
        this.dateFormat = 'yyyy-MM-dd HH:mm:ss';
        this.showDateTime = true;
        break;
      }
    }

    // 获取当前绑定类型
    this.getBindingType();
  }

  /**
   * 获取当前绑定类型
   */
  private getBindingType() {
    this.bindingType = BINDING_TYPE_CUSTOM;

    const allowedBindingType = this.editorParams.allowedBindingType;
    if (allowedBindingType) {
      const types = allowedBindingType.split(',');
      this.canBindForm = types.includes(BINDING_TYPE_FORM);
      this.canBindLocaleVar = types.includes(BINDING_TYPE_LOCAL_VAR);
      this.canBindRemoteVar = types.includes(BINDING_TYPE_REMOTE_VAR);
      this.canBindCustom = types.includes(BINDING_TYPE_CUSTOM);

      this.bindingType = types[0];
    }

    if (this.value || typeof (this.value) === 'boolean') {
      // value为字符串或布尔值
      if (!this.value.type) {
        this.bindingType = BINDING_TYPE_CUSTOM;
        this.customBinding = this.value;
      } else {
        // value为绑定字段或变量或表达式
        this.bindingType = this.value.type;
      }
    }
  }

  /**
   * 组装当前支持的绑定方式数组，用于radiogroup
   */
  private assembleBindingTypeEnumData() {
    if (this.canBindCustom) {
      this.bindingTypeEnumData.push({ value: 'Custom', text: '自定义' });
    }
    if (this.canBindForm) {
      this.bindingTypeEnumData.push({ value: 'Form', text: '绑定字段' });
    }
    if (this.canBindLocaleVar) {
      this.bindingTypeEnumData.push({ value: 'LocaleVariable', text: '绑定组件变量' });
    }
    if (this.canBindRemoteVar) {
      this.bindingTypeEnumData.push({ value: 'RemoteVariable', text: '绑定表单变量' });
    }

    // if (this.editorParams.showExpression) {
    //   this.bindingTypeEnumData.push({ value: 'Expression', text: '表达式' });
    // }
  }


  /**
   * 切换绑定类型
   */
  changeBindingType() {
    switch (this.bindingType) {
      case BINDING_TYPE_CUSTOM: {
        this.treeCols = [];
        this.treeData = [];
        break;
      }
      case BINDING_TYPE_FORM: {
        this.treeCols = this.fieldsTreeCols;
        this.treeData = this.fieldsTreeData;
        break;
      }
      case BINDING_TYPE_LOCAL_VAR: {
        this.treeCols = this.variableTreeCols;
        this.treeData = this.localVarTreeData;
        break;
      }
      case BINDING_TYPE_REMOTE_VAR: {
        this.treeCols = this.variableTreeCols;
        this.treeData = this.remoteVarTreeData;
        break;
      }
    }
    this.treeTable.clearSelections();

    // 离开表达式界面时，保存当前填写的表达式值
    // if (this.editorParams.showExpression && this.bindingType !== BINDING_TYPE_EXPRESSION && this.expressionEditorComponent) {
    //   this.expressionValue = this.expressionEditorComponent.expEditor.getExpr() || '';
    // }
  }
  /**
   * 绑定字段或变量时，组装树表数据
   */
  private assembleTreeData() {

    switch (this.bindingType) {
      case BINDING_TYPE_FORM: {
        this.treeCols = this.fieldsTreeCols;
        this.treeData = this.fieldsTreeData;

        this.selectTreeNode(this.value);
        break;
      }
      case FormBindingType.Variable: {
        const variableCategory = this.getVaribleCategoryTypeById(this.value && this.value.field);

        if (variableCategory === FormVariableCategory.remote) { // 绑定remote变量
          this.treeCols = this.variableTreeCols;
          this.treeData = this.remoteVarTreeData;
          this.bindingType = BINDING_TYPE_REMOTE_VAR;
        } else { // 绑定组件本地变量
          this.treeCols = this.variableTreeCols;
          this.treeData = this.localVarTreeData;
          this.bindingType = BINDING_TYPE_LOCAL_VAR;
        }

        this.selectTreeNode(this.value);
        break;
      }
      case BINDING_TYPE_REMOTE_VAR: {
        this.treeCols = this.variableTreeCols;
        this.treeData = this.remoteVarTreeData;
        break;
      }
      case BINDING_TYPE_LOCAL_VAR: {
        this.treeCols = this.variableTreeCols;
        this.treeData = this.localVarTreeData;
        break;
      }
    }
  }

  /**
   * 树表定位已有记录
   */
  selectTreeNode(binding: any) {
    if (!binding) {
      return;
    }
    const bindingId = binding.field || binding.id;
    if (!bindingId) {
      return;
    }
    this.ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        try {
          this.treeTable.selectNode(bindingId);
        } catch (e) {
          this.treeTable.clearSelections();
          // console.log('已绑定字段或变量不存在！');
        }
      });
    });
  }

  /**
   * 字段/变量是否可选中
   * @param rowNode 行数据
   */
  canChecked(rowNode) {

    switch (this.bindingType) {
      case BINDING_TYPE_FORM: {
        if (rowNode.data.$type === 'SimpleField') {
          return true;
        } else {
          return false;
        }
      }
      default: {
        return rowNode.selectable;
      }
    }

  }


  /**
   * 取消
   */
  clickCancel() {
    this.closeModal.emit();
  }



  /**
   * 确定
   */
  clickConfirm() {
    this.clearOriginalExpression();

    // 绑定：自定义
    if (this.bindingType === BINDING_TYPE_CUSTOM) {
      this.getCustomBinding();
      this.submitModal.emit({ value: this.customBinding });
      return;
    }
    // 绑定：表达式
    if (this.bindingType === BINDING_TYPE_EXPRESSION) {
      const expressionId = this.setExpression();
      this.submitModal.emit({
        value: {
          type: BINDING_TYPE_EXPRESSION,
          expressionId
        }
      });
      return;
    }
    // 绑定：字段、变量
    if (!this.treeTable.selectedRow) {
      const msg = this.bindingType === BINDING_TYPE_FORM ? '字段' : '变量';
      this.notifyService.warning('请选择' + msg + '！');
      return;
    }
    const selectedRow = this.treeTable.selectedRow;
    const selectedData = selectedRow.data;
    const viewModelId = this.editorParams.viewModelId;

    let newValue;
    switch (this.bindingType) {
      case BINDING_TYPE_FORM: {
        newValue = {
          type: BINDING_TYPE_FORM,
          path: selectedData.bindingField,
          field: selectedData.id,
          fullPath: selectedData.path
        };
        break;
      }
      case BINDING_TYPE_LOCAL_VAR: {
        newValue = {
          type: FormBindingType.Variable,
          path: selectedRow['viewModelId'] === viewModelId ? selectedData.code : 'root-component.' + selectedData.code,
          field: selectedData.id,
          fullPath: selectedData.code
        };
        break;
      }
      case BINDING_TYPE_REMOTE_VAR: {
        newValue = {
          type: FormBindingType.Variable,
          path: 'root-component.' + selectedData.code,
          field: selectedData.id,
          fullPath: selectedData.code
        };
        break;
      }
    }

    this.submitModal.emit({ value: newValue });
  }

  /**
   * 初始化表达式相关配置
   */
  private initExpression() {
    if (!this.editorParams.showExpression) {
      return;
    }
    this.expressionParams = {
      fieldId: this.editorParams.bindingFieldId,
      viewModelId: this.editorParams.viewModelId,
      expType: this.editorParams.expressionType
    };
    // 必填表达式需要配置提示消息
    if (this.editorParams.expressionType === 'require') {
      this.expressionParams.message = '';
    }
    if (!this.value || !this.value.expressionId || !this.editorParams.bindingFieldId) {
      return;
    }
    const expField = this.domService.expressions.find(e => e.fieldId === this.editorParams.bindingFieldId);
    if (!expField) {
      return;
    }
    this.originalExpConfig = expField.expression.find(exp => exp.id === this.value.expressionId);
    this.expressionValue = this.originalExpConfig.value;

    if (this.editorParams.expressionType === 'require') {
      this.expressionParams.message = this.originalExpConfig.message;
    }
  }

  /**
   * 保存表达式
   */
  private setExpression() {
    // const newExpr = this.expressionEditorComponent.expEditor.getExpr() || '';
    // return this.expressionEditorComponent.saveExpression(newExpr);

  }
  /**
   * 清除原表达式
   */
  private clearOriginalExpression() {
    if (this.value && this.value.type === BINDING_TYPE_EXPRESSION && this.bindingType !== BINDING_TYPE_EXPRESSION) {
      const exp = this.domService.expressions.find(e => e.fieldId === this.editorParams.bindingFieldId);
      if (!exp || !exp.expression) {
        return;
      }

      exp.expression = exp.expression.filter(e => e.type !== this.editorParams.expressionType);
    }
  }
  /**
   * booleanOrString类型的自定义绑定：初始化
   */
  private initCustomBoolOrString() {
    if (this.bindingType !== BINDING_TYPE_CUSTOM) {
      return;
    }
    if (this.editorParams.customType !== BindingCustomType.booleanOrString) {
      return;
    }
    if (typeof (this.value) === 'boolean') {
      this.customBoolAndStringRadioValue = this.value;
    } else {
      this.customBoolAndStringRadioValue = 'string';
      if (typeof (this.value) === 'string') {
        this.customStringValue = this.value || '';
      }
    }
  }

  /**
   * selectOrString类型的自定义绑定：初始化
   */
  private initCustomSelectOrString() {
    if (this.bindingType !== BINDING_TYPE_CUSTOM) {
      this.customBoolAndStringRadioValue = null;
      return;
    }
    if (this.editorParams.customType !== BindingCustomType.selectOrString) {
      return;
    }
    if (!this.editorParams.selectConfig.options || !this.editorParams.selectConfig.idField) {
      return;
    }
    const valueOptions = this.editorParams.selectConfig.options.map(option => option[this.editorParams.selectConfig.idField]);

    if (this.value && valueOptions.includes(this.value)) {
      this.customBoolAndStringRadioValue = this.value;
    } else {
      this.customBoolAndStringRadioValue = 'string';
      if (typeof (this.value) === 'string') {
        this.customStringValue = this.value || '';
      }
    }
  }



  /**
   * booleanOrString类的自定义绑定：获取自定义绑定值
   */
  getCustomBinding() {
    if (this.editorParams.customType === BindingCustomType.booleanOrString ||
      this.editorParams.customType === BindingCustomType.selectOrString) {
      if (this.customBoolAndStringRadioValue === 'string') {
        this.customBinding = this.customStringValue;
      } else {
        this.customBinding = this.customBoolAndStringRadioValue;
      }
    }
  }

  /**
   * 根据变量id获取变量分类
   * @param variableId 变量id
   */
  private getVaribleCategoryTypeById(variableId: string): string {
    const viewModels = this.domService.viewmodels;
    if (!viewModels || viewModels.length === 0) {
      return;
    }

    for (const viewModel of viewModels) {
      const variable = viewModel.states.find(v => v.id === variableId);
      if (variable) {
        return variable.category;
      }
    }


  }
}


class BindingCustomEditorParams {
  /** 弹窗标题 */
  public modalTitle?: string;
  /** 控件所在视图模型ID */
  public viewModelId: string;

  /** 允许绑定的类型---默认'Custom,LocaleVariable,RemoteVariable' */
  public allowedBindingType: string;

  /** 自定义数据的类型：目前支持string/boolean/select/booleanOrString/selectOrString */
  public customType: BindingCustomType;

  /** 自定义类型为下拉框时，下拉框需要的配置项 */
  public selectConfig: {
    idField: '',
    textField: '',
    options: any[]
  };

  /**
   * 是否支持表达式配置项
   */
  public showExpression?= false;

  /** 当前控件绑定的字段或变量的ID ，在支持表达式配置时，必填 */
  public bindingFieldId?: string;

  /** 表达式类型 */
  public expressionType?: string;

  /** 表达式提示消息 */
  public message?: string;


  public maxDate: string;

  public minDate: string;
}

/**
 * 绑定类型
 */
export enum BindingCustomType {
  /**
   * 字符串
   */
  string = 'string',
  /**
   * 布尔值（以下拉框展示）
   */
  boolean = 'boolean',
  /**
   * 下拉选择
   */
  select = 'select',
  /**
   * 布尔值或者字符串（目前的场景是配置状态机）
   */
  booleanOrString = 'booleanOrString',

  selectOrString = 'selectOrString',

  date = 'date',

  datetime = 'datetime'
}
